package com.dq.controller.sys;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dq.annotation.aop.SysLog;
import com.dq.context.Constant;
import com.dq.exception.customException.AdminException;
import com.dq.controller.in.base.BaseAdminQuery;
import com.dq.controller.op.opmerchant.in.query.SysRoleQuery;
import com.dq.vo.ListVo;
import com.dq.vo.Vo;
import com.dq.vo.baseVo.VO;
import com.dq.domain.base.impl.BaseDaoImpl;
import com.dq.domain.sys.menu.SysMenu;
import com.dq.domain.sys.role.SysRole;
import com.dq.domain.sys.role.SysRoleSection;
import com.dq.domain.sys.role.SysRoleMenu;
import com.dq.domain.sys.role.SysUserRole;
import com.dq.domain.sys.section.SysSection;
import com.dq.domain.sys.user.user.BossUser;
import com.dq.domain.sys.user.user.base.SysUser;
import com.dq.service.AllService;
import com.dq.utils.BeanNullUtil;
import com.dq.validator.ValidatorUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.BeanUtils;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 角色管理
 *
 * @author aaaa
 * @date 2016年11月8日 下午2:18:33
 */
@Api(description = "角色管理")
@RestController
@RequestMapping("/sys/role")
public class SysRoleController extends AllService {
    /**
     * 所有状态（禁用/启用） 角色 (分页)
     * - 用来管理角色
     */
    @ApiOperation("角色列表(分页): 如果不是超级管理员，则只查询自己创建的角色列表")
    @PostMapping("/list")
    @RequiresPermissions("sys:role:list")
    public Vo list(@RequestBody SysRoleQuery roleQuery) throws AdminException {
        roleQuery.format();
        SysUser user = sysUserService.getUser();
        if(user.getSection() == null || user.getSection().getId() == null) {
            throw new AdminException("登录账号门店信息异常");
        }
        // 如果不是超级管理员，则只查询自己创建的角色列表
        boolean isAdminRole = sysRoleService.isAdminRole(user);
        if (!isAdminRole) {
            roleQuery.setCreateUser(user);
        }

        Map<String, Object> query = roleQuery.parseMap();
        if(StringUtils.isNotBlank(roleQuery.getRoleName())) {
            query.put("roleName" + BaseDaoImpl.likeSqlStr, BaseAdminQuery.likeSql(roleQuery.getRoleName()));
            query.remove("roleName");
        }

        // 关联部门
        query.put("dept", user.getSection());

        List<SysRole> list = dao.find(dao.query2Hql(SysRole.class, query), query);
        PageHelper.startPage(roleQuery.getPage(), roleQuery.getSize());
        PageInfo pageInfo = new PageInfo((List<SysRole.Vo>) VO.toVOCollection(list));
        return new Vo(pageInfo);
    }

    /**
     * 用户分配角色时， 展示的角色列表 [只获取启用状态]
     * - 用来角色关联用户
     */
    @ApiOperation("用户分配角色时， 展示的角色列表")
    @GetMapping("/roleWhole")
    public ListVo findRoleWhole(){
        SysUser user = sysUserService.getUser();
        if(user.getSection() == null || user.getSection().getId() == null) {
            throw new AdminException("登录账号门店信息异常");
        }
        Map<String, Object> query = new HashMap<>(16);

        query.put("status", SysRole.Status.on);
        if(!sysRoleService.isAdminRole(user)) {
            query.put("createUser", user);
        }

        // 关联部门
        query.put("dept", user.getSection());
        List<SysRole> list = dao.find(dao.queryAdminHql(SysRole.class, query), query);

        List<SysRole.UserAddRoleVo> userAddRoleVos = new ArrayList<>();
        list.forEach(sysRole -> {
            userAddRoleVos.add(sysRole.toUserAddRoleVo());
        });
        return new ListVo(userAddRoleVos);
    }

    /**
     * 所有状态（禁用/启用） 角色
     */
    @ApiOperation("角色列表（不分页）： 只查询自己创建的角色列表")
    @GetMapping("/select")
    @RequiresPermissions("sys:role:select")
    public Vo<SysRole> select() throws AdminException {
        SysUser user = sysUserService.getUser();
        if(user.getSection() == null || user.getSection().getId() == null) {
            throw new AdminException("登录账号门店信息异常");
        }

        SysRoleQuery roleQuery = new SysRoleQuery();
        roleQuery.setCreateUser(user);
        Map<String, Object> query = roleQuery.parseMap();
        // 关联部门
        query.put("dept", user.getSection());
        List<SysRole> list = dao.find(dao.queryAdminHql(SysRole.class, query), query);

        return new Vo(VO.toVOCollection(list));
    }

    @ApiOperation("角色详情： 包括关联菜单ID/部门ID")
    @GetMapping("/info/{roleId}")
    @RequiresPermissions("sys:role:info")
    public Vo<SysRole> info(@PathVariable @ApiParam(value = "角色id") Long roleId) {
        SysRole role = dao.get(SysRole.class, roleId);
        if(role == null) {
            throw new AdminException("无对应角色");
        }

        SysRole.Vo sysRoleVo = (SysRole.Vo) role.toVO();

        // 查询角色 关联菜单 【todo 未区分是否禁用】
        List<Long> menuIdList = sysRoleService.findAllMenuIdByRole(role);
        sysRoleVo.setMenuIdList(menuIdList);

        // 查询角色 关联部门
        List<Long> deptIdList = sysRoleService.findAllDeptIdByRole(role);
        sysRoleVo.setDeptIdList(deptIdList);

        return new Vo(sysRoleVo);
    }

    @ApiOperation("保存角色")
    @SysLog("保存角色")
    @PostMapping("/save/{sysDeptId}")
    @RequiresPermissions("sys:role:save")
    public Vo save(@RequestBody SysRole role) throws AdminException {
        SysUser user = sysUserService.getUser();
        if(user.getSection() == null || user.getSection().getId() == null) {
            throw new AdminException("登录账号门店信息异常");
        }
        ValidatorUtils.validateEntity(role);
        role.setDept(user.getSection());

        sysRoleService.save(role);
        return new Vo(role);
    }
    @ApiOperation("修改角色")
    @SysLog("修改角色")
    @PostMapping("/update/{roleId}")
    @RequiresPermissions("sys:role:update")
    public Vo update(@RequestBody SysRole role, @PathVariable @ApiParam(value = "角色id") Long roleId) throws AdminException {
        SysRole sysRole = dao.get(SysRole.class, roleId);
        if (sysRole == null) {
            throw new AdminException("角色不存在");
        }
        BeanUtils.copyProperties(role, sysRole, BeanNullUtil.getNullPropertyNames(role));
        sysRoleService.update(sysRole);
        return new Vo(HttpStatus.OK);
    }
    @ApiOperation("删除角色： 同时删除角色关联表")
    @SysLog("删除角色")
    @PostMapping("/delete/{roleId}")
    @RequiresPermissions("sys:role:delete")
    public Vo delete(@PathVariable @ApiParam(value = "角色id") Long roleId) {
        SysRole sysRole = dao.get(SysRole.class, roleId);
        if(sysRole == null) {
            throw new AdminException("角色不存在");
        }
        sysRoleService.deleteBath(sysRole);
        return new Vo(HttpStatus.OK);
    }

    /**
     * todo 未区分是否禁用
     */
    @ApiOperation("获取用户-角色 中间关联表")
    @PostMapping("/getUserRole/{roleId}")
    @RequiresPermissions("sys:role:getUserRole")
    public Vo getUserRole(@PathVariable @ApiParam(value = "角色id") Long roleId) throws AdminException {
        SysRole sysRole = dao.get(SysRole.class, roleId);
        if (null == sysRole) {
            throw new AdminException("角色不存在");
        }
        List<SysUserRole> sysUserRoles = sysUserRoleRepository.findBySysRole(sysRole);
        return new Vo(VO.toVOCollection(sysUserRoles));
    }
    /**
     * todo 未区分是否禁用
     */
    @ApiOperation("获取角色-菜单 中间关联表")
    @PostMapping("/getRoleMenu/{roleId}")
    @RequiresPermissions("sys:role:getRoleMenu")
    public Vo getRoleMenu(@PathVariable @ApiParam(value = "角色id") Long roleId) throws AdminException {
        SysRole sysRole = dao.get(SysRole.class, roleId);
        if (null == sysRole) {
            throw new AdminException("角色不存在");
        }
        List<SysRoleMenu> sysRoleMenus = sysRoleMenuRepository.findBySysRole(sysRole);
        return new Vo(VO.toVOCollection(sysRoleMenus));
    }

    @ApiOperation("角色关联菜单")
    @PostMapping("/roleMenu/{roleId}")
    @RequiresPermissions("sys:role:roleMenu")
    public Vo roleMenu(@RequestBody List<Long> menuIds, @PathVariable @ApiParam(value = "角色id") Long roleId) throws AdminException {
        SysRole sysRole = dao.get(SysRole.class, roleId);
        if (sysRole == null) {
            throw new AdminException("角色不存在");
        }
        List<SysRoleMenu> sysRoleMenusNew = new ArrayList<>();
        if (!menuIds.isEmpty()) {
            List<SysMenu> sysMenus = sysMenuRepository.findByIdIn(menuIds);
            for (SysMenu sysMenu : sysMenus) {
                SysRoleMenu sysRoleMenu = new SysRoleMenu();
                sysRoleMenu.setSysMenu(sysMenu);
                sysRoleMenu.setSysRole(sysRole);
                sysRoleMenusNew.add(sysRoleMenu);
            }
        }
        List<SysRoleMenu> sysRoleMenus = sysRoleMenuRepository.findBySysRole(sysRole);
        if (!sysRoleMenus.isEmpty()) {
            sysRoleMenuRepository.deleteAll(sysRoleMenus);
        }
        if(sysRoleMenusNew.size() > 0) {
            sysRoleMenuRepository.saveAll(sysRoleMenusNew);
        }

        return new Vo(HttpStatus.OK);
    }

    @ApiOperation("角色关联用户")
    @PostMapping("/roleUrserAuth/{roleId}")
    @RequiresPermissions("sys:role:roleUrserAuth")
    public Vo roleUrserAuth(@RequestBody List<Long> userIds, @PathVariable @ApiParam(value = "角色id") Long roleId) throws AdminException {
        SysUser loginUser = sysUserService.getUser();

        SysRole sysRole = dao.get(SysRole.class, roleId);
        if (sysRole == null) {
            throw new AdminException("角色不存在");
        }
        List<SysUserRole> sysUserRolesNew = new ArrayList<>();
        if (!userIds.isEmpty()) {
            List<SysUser> sysUsers = sysUserRepository.findByIdIn(userIds);
            for (SysUser sysUser : sysUsers) {
                if(String.valueOf(Constant.ADMIN_ID).equals(sysUser.getId().toString())) {
                    continue;
                }
                // 之账号
                if(Constant.ROLE_CODE_LIST.get(3).equals(sysRole.getCode())) {
                    if(!(sysUser instanceof BossUser)) {
                        throw new AdminException("分配账号非 BossUser");
                    }
                    BossUser bossUser = (BossUser) sysUser;
                    if(StringUtils.isBlank(bossUser.getCity())) {
                        throw new AdminException(bossUser.getUsername() + "账号未选择负责区域");
                    }
                }

                SysUserRole sysUserRole = new SysUserRole();
                sysUserRole.setCreateUser(loginUser);
                sysUserRole.setUpdateUser(loginUser);
                sysUserRole.setSysRole(sysRole);
                sysUserRole.setSysUser(sysUser);
                sysUserRolesNew.add(sysUserRole);
            }
        }
        List<SysUserRole> sysUserRoles = sysUserRoleRepository.findBySysRole(sysRole);
        if (!sysUserRoles.isEmpty()) {
            List<SysUserRole>delList = new ArrayList<>();
            // 不删除admin 账号的超级管理角色
            for (SysUserRole sysUserRole : sysUserRoles) {
                if(!sysUserRole.getSysUser().getId().toString().equals(String.valueOf(Constant.ADMIN_ID))) {
                    delList.add(sysUserRole);
                }
            }

            if(delList.size() > 0) {
                sysUserRoleRepository.deleteAll(delList);
            }
        }
        if(sysUserRolesNew.size() > 0) {
            sysUserRoleRepository.saveAll(sysUserRolesNew);
        }

        return new Vo(HttpStatus.OK);
    }

    @ApiOperation("角色关联部门")
    @PostMapping("/roleDeptAuth/{roleId}")
    @RequiresPermissions("sys:role:roleDeptAuth")
    public Vo roleDeptAuth(@RequestBody List<Long> deptIds, @PathVariable @ApiParam(value = "角色id") Long roleId) throws AdminException {
        SysRole sysRole = dao.get(SysRole.class, roleId);
        if (sysRole == null) {
            throw new AdminException("角色不存在");
        }
        List<SysRoleSection> list = sysRoleSectionRepository.findByDeletedFalseAndSysRole(sysRole);
        if (!list.isEmpty()) {
            sysRoleSectionRepository.deleteAll(list);
        }
        if (deptIds.isEmpty()) {
            return new Vo(HttpStatus.OK);
        }
        list = new ArrayList<>();
        List<SysSection> sysDepts = sysSectionRepository.findByIdIn(deptIds);
        for (SysSection section : sysDepts) {
            SysRoleSection sysRoleSection = new SysRoleSection();
            sysRoleSection.setSysRole(sysRole);
            sysRoleSection.setSection(section);
            list.add(sysRoleSection);
        }
        sysRoleSectionRepository.saveAll(list);
        return new Vo(HttpStatus.OK);
    }

    @ApiOperation("查询指定用户 的 角色id列表")
    @PostMapping("/id/list/{id}")
    public Vo idList(@PathVariable @ApiParam("id") Long id){
        List<SysUserRole> sysUserRoles = sysUserRoleRepository.findBySysUser(dao.get(SysUser.class,id));
        List<Long> longs = new ArrayList<>();
        sysUserRoles.forEach(sysUserRole -> {
            longs.add(sysUserRole.getSysRole().getId());
        });
        Long[] longsArr = {};
        longsArr = longs.toArray(longsArr);
        return new Vo(longsArr);
    }

    @ApiOperation("boss查询所有角色")
    @GetMapping("/findAllRole")
    public Vo findAllRole()throws AdminException{
        List<SysRole> sysRoles = sysRoleRepository.findByDeletedFalse();
        JSONArray array = new JSONArray();
        sysRoles.forEach(sysRole -> {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("id",sysRole.getId());
            jsonObject.put("name",sysRole.getRoleName());
            array.add(jsonObject);
        });
        return new Vo(array);
    }
}
